/* sw420实现振动监测  */
#include "sw420.h"

rt_uint8_t sw420_intensity;            // Vibration intensity (0-100)

vibration_data_t vib_data = {
    .sample_interval = 100,        // 默认100ms采样一次
    .window_size = 500,            // 默认统计窗口500ms
};

/* 平滑滤波缓冲区大小 */
static uint32_t smooth_buffer[SMOOTH_FILTER_SIZE];
static uint32_t buffer_index = 0;

/* 历史触发计数缓冲区 */
static uint32_t trigger_history[TRIGGER_HISTORY_SIZE];
static uint32_t history_index = 0;

/* Interrupt callback function */
void sw_interrupt_callback(void *args)
{
    rt_base_t level = rt_pin_read(SW_PIN);
    if (level == PIN_LOW) {  // 下降沿触发
        rt_enter_critical();  // 进入临界区
        vib_data.trigger_count++;
        rt_exit_critical();   // 退出临界区
    }
}

/* 非线性映射函数 - 增强不同振动强度之间的差异，最大值调整为100 */
uint8_t map_intensity(uint32_t freq)
{
    if (freq < 10) {
        return freq * 4;               // 低频区域放大4倍
    } else if (freq < 30) {
        return 40 + (freq - 10) * 1.25; // 中频区域调整放大倍数
    } else if (freq < 50) {
        return 65 + (freq - 30) * 0.75; // 中高频区域调整放大倍数
    } else {
        return 80 + (freq - 50) * 0.4;  // 高频区域压缩变化，确保最大值为100
    }
}

/* 滑动平均滤波 */
uint32_t apply_smoothing(uint32_t raw_value)
{
    static bool buffer_initialized = false;

    /* 首次调用时初始化缓冲区 */
    if (!buffer_initialized) {
        for (int i = 0; i < SMOOTH_FILTER_SIZE; i++) {
            smooth_buffer[i] = raw_value;
        }
        buffer_initialized = true;
    }

    /* 更新缓冲区 */
    smooth_buffer[buffer_index] = raw_value;
    buffer_index = (buffer_index + 1) % SMOOTH_FILTER_SIZE;

    /* 计算平均值 */
    uint32_t sum = 0;
    for (int i = 0; i < SMOOTH_FILTER_SIZE; i++) {
        sum += smooth_buffer[i];
    }

    return sum / SMOOTH_FILTER_SIZE;
}

/* Sampling thread */
void intensity_sample_thread(void *parameter)
{
    uint32_t current_tick;
    uint32_t last_window_tick = rt_tick_get();
    uint32_t last_trigger_count = 0;

    while (1) {
        rt_thread_mdelay(vib_data.sample_interval);  // 等待采样周期

        current_tick = rt_tick_get();

        /* 计算窗口内的触发次数 */
        uint32_t window_triggers = vib_data.trigger_count - last_trigger_count;

        /* 记录历史触发数据 */
        trigger_history[history_index] = window_triggers;
        history_index = (history_index + 1) % TRIGGER_HISTORY_SIZE;

        /* 只有当窗口时间达到时才计算频率和强度 */
        if (current_tick - last_window_tick >= RT_TICK_PER_SECOND * vib_data.window_size / 1000) {
            /* 计算窗口内的总触发次数 */
            uint32_t total_triggers = 0;
            for (int i = 0; i < TRIGGER_HISTORY_SIZE; i++) {
                total_triggers += trigger_history[i];
            }

            /* 计算触发频率(Hz) - 基于整个统计窗口 */
            uint32_t freq = (total_triggers * 1000) / vib_data.window_size;

            /* 映射为0-100的强度值 */
            uint32_t raw_intensity = map_intensity(freq);

            /* 应用平滑滤波 */
            vib_data.intensity = apply_smoothing(raw_intensity);

            /* 更新窗口标记和触发计数 */
            last_window_tick = current_tick;
            last_trigger_count = vib_data.trigger_count;

            sw420_intensity = vib_data.intensity;
          //  rt_kprintf("%d\n", vib_data.intensity); // 注释输出
        }
    }
}

/* MSH command: Configure sampling parameters */
void cmd_vib_config(int argc, char *argv[])
{
    if (argc < 3) {
        rt_kprintf("Usage: vib_config [sample_ms] [window_ms]\n");
        rt_kprintf("sample_ms: Sampling interval (ms), range 10-200\n");
        rt_kprintf("window_ms: Statistics window size (ms), range 200-2000\n");
        return;
    }

    uint32_t sample_ms = strtoul(argv[1], NULL, 10);
    uint32_t window_ms = strtoul(argv[2], NULL, 10);

    if (sample_ms < 10 || sample_ms > 200) {
        rt_kprintf("Error: Sampling interval must be 10-200ms\n");
        return;
    }

    if (window_ms < 200 || window_ms > 2000) {
        rt_kprintf("Error: Window size must be 200-2000ms\n");
        return;
    }

    vib_data.sample_interval = sample_ms;
    vib_data.window_size = window_ms;
    rt_kprintf("Sampling interval updated to %dms, Window size updated to %dms\n",
               sample_ms, window_ms);
}
MSH_CMD_EXPORT(cmd_vib_config, Set vibration sampling parameters);

/* Initialization function */
int vibration_monitor_init(void)
{
    rt_err_t ret;

    /* 初始化振动传感器引脚 */
    rt_pin_mode(SW_PIN, PIN_MODE_INPUT_PULLUP);
    ret = rt_pin_attach_irq(SW_PIN, PIN_IRQ_MODE_FALLING, sw_interrupt_callback, RT_NULL);
    if (ret != RT_EOK) {
        rt_kprintf("Error: Failed to attach interrupt\n");
        return -1;
    }

    ret = rt_pin_irq_enable(SW_PIN, PIN_IRQ_ENABLE);
    if (ret != RT_EOK) {
        rt_kprintf("Error: Failed to enable interrupt\n");
        return -1;
    }

    /* 创建采样线程(低优先级) */
    rt_thread_t sample_thread = rt_thread_create(
        "sw_check",
        intensity_sample_thread,
        RT_NULL,
        sw420_THREAD_STACK_SIZE,  /* 使用定义的栈大小 */
        sw420_THREAD_PRIORITY,    /* 使用定义的优先级 */
        sw420_THREAD_TIMESLICE
    );

    if (sample_thread != RT_NULL) {
        rt_thread_startup(sample_thread);
        LOG_I("Vibration monitor started (Window size: %dms)", vib_data.window_size);
        return 0;
    } else {
        LOG_E("Error: Failed to create sampling thread");
        return -1;
    }
}
INIT_APP_EXPORT(vibration_monitor_init);
